This is a deadlock bug.
One thread calls isAnnotationPresent on an annotated class where
the annotation is not yet initialized for its defining classloader.
This will result in a call on AnnotationType.getInstance, locking the
class object for sun.reflect.annotation.AnnotationType.getInstance will
result in a Class.initAnnotationsIfNecessary for that annotation,
trying to acquire a lock on the class object of that annotation.
In the meanwhile, another thread has requested
Class.getAnnotations for that annotation(!). Since getAnnotations locks
the class object it was requested on, the first thread can't lock it
when it runs into Class.initAnnotationsIfNecessary for that annotation.
But the thread holding the lock will try to acquire the lock for the
class object of sun.reflect.annotation.AnnotationType in
AnnotationType.getInstance which is hold by the first thread, thus
resulting in the deadlock.
The following is an example of deadlock thread dump:
"AnnB":More details about this bug are at JDK-7122142 JIRA page.
waiting to lock monitor 0x0000000006bfdeb0 (object 0x00000007d5ea49e0, a java.lang.Class),
which is held by "AnnA"
"AnnA":
waiting to lock monitor 0x0000000006bfd778 (object 0x00000007d5dfe660, a java.lang.Class),
which is held by "AnnB"
Java stack information for the threads listed above:
===================================================
"AnnB":
at sun.reflect.annotation.AnnotationType.getInstance(AnnotationType.java:81)
- waiting to lock <0x00000007d5ea49e0> (a java.lang.Class for sun.reflect.annotation.AnnotationType) at sun.reflect.annotation.AnnotationParser.parseAnnotation(AnnotationParser.java:221) at sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:88) at sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:70) at java.lang.Class.initAnnotationsIfNecessary(Class.java:3089) - locked <0x00000007d5dfe660> (a java.lang.Class for Test7122142$AnnB) at java.lang.Class.getDeclaredAnnotations(Class.java:3077) at Test7122142$Task.run(Test7122142.java:75) "AnnA": at java.lang.Class.initAnnotationsIfNecessary(Class.java:3086) - waiting to lock <0x00000007d5dfe660> (a java.lang.Class for Test7122142$AnnB) at java.lang.Class.getAnnotation(Class.java:3048) at sun.reflect.annotation.AnnotationType.(AnnotationType.java:131)
at sun.reflect.annotation.AnnotationType.getInstance(AnnotationType.java:84)
- locked <0x00000007d5ea49e0> (a java.lang.Class for sun.reflect.annotation.AnnotationType) at sun.reflect.annotation.AnnotationParser.parseAnnotation(AnnotationParser.java:221) at sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:88) at sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:70) at java.lang.Class.initAnnotationsIfNecessary(Class.java:3089) - locked <0x00000007d5dfd318> (a java.lang.Class for Test7122142$AnnA) at java.lang.Class.getDeclaredAnnotations(Class.java:3077) at Test7122142$Task.run(Test7122142.java:75)
This bug is reproduced under JDK 1.7.0.
It started at JDK 1.7.0, and has been fixed since JDK 1.8.0.
Execute
the following scripts to run the test to reproduce the bug (assume the
location of the jdk7 test project is jdk7_test_home).
Linux:
${jdk7_test_home}/scripts/7122142.sh [--monitoroff] [--javaloc path]
Windows:
%jdk7_test_home%\scripts\7122142.bat [--monitoroff] [--javaloc path]
Example:
Use monitor to report and terminate the program when deadlock happens:
${jdk_test_home}/scripts/7122142.sh
Turn off monitor:
${jdk_test_home}/scripts/7122142.sh
--monitoroff
| Option | Function |
| --monitoroff, -mo | Turn off to stop reporting bug messages and ending program
when the test runs into the expected concurrency bug which is
a deadlock. User has to terminate the program manually when this option is set. |
| --javaloc | The location of JDK that is eligible to reproduce the bug, if your java environment is not eligible.
In this case, it's JDK 1.7.0. It should be the absolute path to the JDK's java starter and ended with "/". For example: ~/jdk/home/jdk1.7.0/bin/ |